/**
 * Copyright(c) ${copyrightYear} ${company}
 * All rights reserved.
 * Created on ${date}
 */
package ${package};

import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.annotation.Resource;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 * 基本的DAO，包括90%的数据库操作
 * 
 * @author ${author}
 * @param <T>
 *            BaseEntity的子类
 */
@SuppressWarnings("unchecked")
public abstract class BaseDAO<T extends BaseEntity>  extends HibernateDaoSupport {

	/**
	 * entityClass
	 */
	private Class<T> entityClass;

	/**
	 * 设置sessionFactory
	 * @param sessionFactory
	 */
	@Resource(name = "sessionFactory")
	public void setSuperSessionFactory(SessionFactory sessionFactory) {
		super.setSessionFactory(sessionFactory);
	}

	/**
	 * 默认的构造方法
	 */
	public BaseDAO() {
		ParameterizedType parameterizedType = (ParameterizedType) this
				.getClass().getGenericSuperclass();
		entityClass = (Class<T>) parameterizedType.getActualTypeArguments()[0];
	}

	/**
	 * 保存
	 * 
	 * @param t
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public void insert(final T t) throws SQLException {
		getSession().persist(t);
	}

	/**
	 * 更新
	 * 
	 * @param t
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public void update(final T t) throws SQLException {
		getSession().merge(t);
	}

	/**
	 * 修改根据hql names 为 null 就表示不要参数
	 * 
	 * @param
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public int updateByHQL(final String hql, final List<String> argNames,
			final List<Object> args) throws SQLException {
		Query query = getSession().createQuery(hql);
		if (argNames != null && args != null) {
			if (argNames.size() != args.size()) {
				throw new SQLException(
						"Length of paramNames array must match length of values array");
			}
			for (int i = 0; i < argNames.size(); i++) {
				query.setParameter(argNames.get(i), args.get(i));
			}
		}
		return query.executeUpdate();
	}

	/**
	 * 修改根据native sql
	 * 
	 * @param t
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public int updateBySQL(final String sql, final List<String> argNames,
			final List<Object> args) throws SQLException {
		Query query = getSession().createSQLQuery(sql);
		if (argNames != null && args != null) {
			if (argNames.size() != args.size()) {
				throw new SQLException(
						"Length of paramNames array must match length of values array");
			}
			for (int i = 0; i < argNames.size(); i++) {
				query.setParameter(argNames.get(i), args.get(i));
			}
		}
		return query.executeUpdate();
	}

	/**
	 * 增加根据hql names 为 null 就表示不要参数
	 * 
	 * @param
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public int insertByHQL(final String hql, final List<String> argNames,
			final List<Object> args) throws SQLException {
		Query query = getSession().createQuery(hql);
		if (argNames != null && args != null) {
			if (argNames.size() != args.size()) {
				throw new SQLException(
						"Length of paramNames array must match length of values array");
			}
			for (int i = 0; i < argNames.size(); i++) {
				query.setParameter(argNames.get(i), args.get(i));
			}
		}
		return query.executeUpdate();
	}

	/**
	 * 增加根据native sql
	 * 
	 * @param t
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public int insertBySQL(final String sql, final List<String> argNames,
			final List<Object> args) throws SQLException {
		Query query = getSession().createSQLQuery(sql);
		if (argNames != null && args != null) {
			if (argNames.size() != args.size()) {
				throw new SQLException(
						"Length of paramNames array must match length of values array");
			}
			for (int i = 0; i < argNames.size(); i++) {
				query.setParameter(argNames.get(i), args.get(i));
			}
		}
		return query.executeUpdate();
	}

	/**
	 * 根据对象删除
	 * 
	 * @param t
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public void delete(final T t) throws SQLException {
		getSession().delete(t);
	}

	/**
	 * 删除所有当前DAO的Entity数据
	 * 
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public void deleteAll() throws SQLException {
		Query query = getSession().createQuery(
				"delete from " + entityClass.getSimpleName());
		query.executeUpdate();
	}

	/**
	 * 根据ID删除
	 * 
	 * @param id
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public void deleteById(final Long id) throws SQLException {
		T t = get(id);
		if (t != null) {
			getSession().delete(t);
		}
	}

	/**
	 * 删除根据hql names 为 null 就表示不要参数
	 * 
	 * @param
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public int deleteByHQL(final String hql, final List<String> argNames,
			final List<Object> args) throws SQLException {
		Query query = getSession().createQuery(hql);
		if (argNames != null && args != null) {
			if (argNames.size() != args.size()) {
				throw new SQLException(
						"Length of paramNames array must match length of values array");
			}
			for (int i = 0; i < argNames.size(); i++) {
				query.setParameter(argNames.get(i), args.get(i));
			}
		}
		return query.executeUpdate();
	}

	/**
	 * 删除根据native sql
	 * 
	 * @param t
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public int deleteBySQL(final String sql, final List<String> argNames,
			final List<Object> args) throws SQLException {
		Query query = getSession().createSQLQuery(sql);
		if (argNames != null && args != null) {
			if (argNames.size() != args.size()) {
				throw new SQLException(
						"Length of paramNames array must match length of values array");
			}
			for (int i = 0; i < argNames.size(); i++) {
				query.setParameter(argNames.get(i), args.get(i));
			}
		}
		return query.executeUpdate();
	}

	/**
	 * 删除集合里面的对象
	 * 
	 * @param entitys
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public void deleteCollection(
			final Collection<? extends BaseEntity<?>> entitys)
			throws SQLException {
		for (BaseEntity<?> entity : entitys) {
			getSession().delete(entity);
		}
	}

	/**
	 * 查找
	 * 
	 * @param id
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public T get(final Long id) throws SQLException {
		if (id == null) {
			return null;
		}
		return (T) getSession().get(entityClass, id);
	}

	/**
	 * 查找 延迟加载
	 * 
	 * @param id
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public T load(final Long id) throws SQLException {
		if (id == null) {
			return null;
		}
		return (T) getSession().load(entityClass, id);
	}

	/**
	 * 根据HQL查询
	 * 
	 * @param hql
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public T uniqueResult(final String hql) throws SQLException {
		return (T) uniqueResultObject(hql);
	}

	/**
	 * 根据HQL查询
	 * 
	 * @param hql
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public T uniqueResult(final String hql, final String name,
			final Object value) throws SQLException {
		List<String> argNames = new ArrayList<String>();
		argNames.add(name);
		List<Object> args = new ArrayList<Object>();
		args.add(value);
		return uniqueResult(hql, argNames, args);
	}

	/**
	 * 根据HQL查询
	 * 
	 * @param hql
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public T uniqueResult(final String hql, final List<String> argNames,
			final List<Object> args) throws SQLException {
		return (T) uniqueResultObject(hql, argNames, args);
	}

	/**
	 * 根据HQL查询
	 * 
	 * @param hql
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public Object uniqueResultObject(final String hql) throws SQLException {
		return uniqueResultObject(hql, (List<String>) null, (List<Object>) null);

	}

	/**
	 * 根据HQL查询
	 * 
	 * @param hql
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public Object uniqueResultObject(final String hql, final String name,
			final Object value) throws SQLException {
		List<String> argNames = new ArrayList<String>();
		argNames.add(name);
		List<Object> args = new ArrayList<Object>();
		args.add(value);
		return uniqueResultObject(hql, argNames, args);
	}

	/**
	 * 根据HQL查询
	 * 
	 * @param hql
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public Object uniqueResultObject(final String hql,
			final List<String> argNames, final List<Object> args)
			throws SQLException {
		Query query = getSession().createQuery(hql);
		if (argNames != null && args != null) {
			if (argNames.size() != args.size()) {
				throw new SQLException(
						"Length of paramNames array must match length of values array");
			}
			for (int i = 0; i < argNames.size(); i++) {
				query.setParameter(argNames.get(i), args.get(i));
			}
		}
		try {
			return query.uniqueResult();
		} catch (HibernateException e) {
			// 忽略
		}
		return null;
	}

	/**
	 * 根据SQL查询
	 * 
	 * @param sql
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public Object uniqueResultObjectBySQL(final String sql) throws SQLException {
		return uniqueResultObjectBySQL(sql, (List<String>) null,
				(List<Object>) null);

	}

	/**
	 * 根据SQL查询
	 * 
	 * @param sql
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public Object uniqueResultObjectBySQL(final String sql, final String name,
			final Object value) throws SQLException {
		List<String> argNames = new ArrayList<String>();
		argNames.add(name);
		List<Object> args = new ArrayList<Object>();
		args.add(value);
		return uniqueResultObjectBySQL(sql, argNames, args);
	}

	/**
	 * 根据SQL查询
	 * 
	 * @param sql
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public Object uniqueResultObjectBySQL(final String sql,
			final List<String> argNames, final List<Object> args)
			throws SQLException {
		Query query = getSession().createSQLQuery(sql);
		if (argNames != null && args != null) {
			if (argNames.size() != args.size()) {
				throw new SQLException(
						"Length of paramNames array must match length of values array");
			}
			for (int i = 0; i < argNames.size(); i++) {
				query.setParameter(argNames.get(i), args.get(i));
			}
		}
		try {
			return query.uniqueResult();
		} catch (HibernateException e) {
			// 忽略
		}
		return null;
	}

	/**
	 * 查询所有
	 * 
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List<T> list() throws SQLException {
		return listOrderBy(null);
	}

	/**
	 * 查询所有，后面的orderbyStr，不需要跟order by ， 比如查询所有UserEntity，并且根据ID 降序，那么就是
	 * dao.list("id desc"), 根据多个字段就用排序就用list("id desc ,name desc")；
	 * 
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List<T> listOrderBy(final String orderbyStr) throws SQLException {
		String hql = " from " + entityClass.getSimpleName();
		if (orderbyStr != null) {
			hql = "  from " + entityClass.getSimpleName() + " order by "
					+ orderbyStr;
		}
		return list(hql, null);
	}

	/**
	 * 根据HQL查询
	 * 
	 * @param hql
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List list(final String hql) throws SQLException {
		return list(hql, null);
	}

	/**
	 * 带一个参数的HQL查询
	 * 
	 * @param hql
	 * @param value
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List list(final String hql, final Object value) throws SQLException {
		Object[] values = { value };
		return list(hql, values);
	}

	/**
	 * 带多个参数的HQL查询
	 * 
	 * @param HQL
	 * @param values
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List list(final String hql, final String name, final Object value)
			throws SQLException {
		List<String> argNames = new ArrayList<String>();
		argNames.add(name);
		List<Object> args = new ArrayList<Object>();
		args.add(value);
		return list(hql, argNames, args);
	}

	/**
	 * 带需带参数的HQL查询
	 * 
	 * @param hql
	 * @param values
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List list(final String hql, final Object[] values)
			throws SQLException {
		Query query = getSession().createQuery(hql);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		return query.list();
	}

	/**
	 * 指定参数名的查询
	 * 
	 * @param hql
	 * @param argNames
	 * @param args
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List list(final String hql, final List<String> argNames,
			final List<Object> args) throws SQLException {
		Query query = getSession().createQuery(hql);
		if (argNames != null && args != null) {
			if (argNames.size() != args.size()) {
				throw new SQLException(
						"Length of paramNames array must match length of values array");
			}
			for (int i = 0; i < argNames.size(); i++) {
				query.setParameter(argNames.get(i), args.get(i));
			}
		}
		return query.list();
	}

	/**
	 * 根据SQL查询
	 * 
	 * @param sql
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List listBySQL(final String sql) throws SQLException {
		return listBySQL(sql, null, null);
	}

	/**
	 * 根据SQL查询
	 * 
	 * @param sql
	 * @param argNames
	 * @param args
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List listBySQL(final String sql, final List<String> argNames,
			final List<Object> args) throws SQLException {
		Query query = getSession().createSQLQuery(sql);
		if (argNames != null && args != null) {
			if (argNames.size() != args.size()) {
				throw new SQLException(
						"Length of paramNames array must match length of values array");
			}
			for (int i = 0; i < argNames.size(); i++) {
				query.setParameter(argNames.get(i), args.get(i));
			}
		}
		return query.list();
	}

	/**
	 * 分页的HQL查询
	 * 
	 * @param start
	 * @param limit
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List pageQuery(final Integer start, final Integer limit)
			throws SQLException {
		String hql = "from " + entityClass.getSimpleName();
		return pageQuery(hql, (Object) null, start, limit);

	}

	/**
	 * 分页的HQL查询
	 * 
	 * @param hql
	 * @param start
	 * @param limit
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List pageQuery(final String hql, final Integer start,
			final Integer limit) throws SQLException {
		return pageQuery(hql, new ArrayList<Object>(), start, limit);

	}

	/**
	 * 带一个参数的分页HQL查询
	 * 
	 * @param hql
	 * @param value
	 * @param start
	 * @param limit
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List pageQuery(final String hql, final Object value,
			final Integer start, final Integer limit) throws SQLException {
		List<Object> values = new ArrayList<Object>();
		if (value != null) {
			values.add(value);
		}
		return pageQuery(hql, values, start, limit);

	}

	/**
	 * 带很多参数的分页查询
	 * 
	 * @param hql
	 * @param values
	 * @param start
	 * @param limit
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List pageQuery(final String hql, final List<Object> values,
			final Integer start, final Integer limit) throws SQLException {
		Query query = getSession().createQuery(hql);
		for (int i = 0; i < values.size(); i++) {
			query.setParameter(i, values.get(i));
		}
		query.setFirstResult(start).setMaxResults(limit);
		return query.list();
	}

	/**
	 * 指定参数名的分页查询
	 * 
	 * @param hql
	 * @param argNames
	 * @param args
	 * @param start
	 * @param limit
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List pageQuery(final String hql, final String name,
			final Object value, final Integer start, final Integer limit)
			throws SQLException {
		List<String> argNames = new ArrayList<String>();
		argNames.add(name);
		List<Object> args = new ArrayList<Object>();
		args.add(value);
		return pageQuery(hql, argNames, args, start, limit);

	}

	/**
	 * 指定参数名的分页查询
	 * 
	 * @param hql
	 * @param argNames
	 * @param args
	 * @param start
	 * @param limit
	 * @return
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public List pageQuery(final String hql, final List<String> argNames,
			final List<Object> args, final Integer start, final Integer limit)
			throws SQLException {
		Query query = getSession().createQuery(hql);
		if (argNames != null && args != null) {
			if (argNames.size() != args.size()) {
				throw new SQLException(
						"Length of paramNames array must match length of values array");
			}
			for (int i = 0; i < argNames.size(); i++) {
				query.setParameter(argNames.get(i), args.get(i));
			}
		}
		query.setFirstResult(start).setMaxResults(limit);
		return query.list();

	}

	/**
	 * 清空EntityManager
	 * 
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public void clear() throws SQLException {
		getSession().clear();
	}

	/**
	 * 关闭EntityManager
	 * 
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public void close() throws SQLException {
		getSession().close();
	}

	/**
	 * 刷新EntityManager
	 * 
	 * @throws SQLException
	 *             所有SQL异常
	 */
	public void flush() throws SQLException {
		getSession().flush();
	}

	/**
	 * 获取Session ，非特殊情况请勿使用
	 * 
	 */
	public Session getHibernateSession() {
		return getSession();
	}
}
